﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Net;

namespace Sofire.DataComm.Remoting.Server.Settings
{
    /// <summary>
    /// 应用域配置信息。
    /// </summary>
    public class ApplicationSetting : SettingBase, IEnumerable<HostSetting>
    {
        private Dictionary<string, HostSetting> _Hosts;

        /// <summary>
        /// 获取指定主机名称的 <see cref="Sofire.DataComm.Remoting.Server.Settings.HostSetting"/>。
        /// </summary>
        /// <param name="hostName">主机的名称。</param>
        /// <returns>返回查找到的主机或 null 值。</returns>
        public HostSetting this[string hostName]
        {
            get
            {
                HostSetting host;
                if(this._Hosts.TryGetValue(hostName, out host)) return host;
                return null;
            }
        }

        /// <summary>
        /// 获取应用程序配置下的所有主机配置。
        /// </summary>
        public IEnumerable<HostSetting> Hosts
        {
            get
            {
                if(this._Hosts == null) return new List<HostSetting>(0);
                else return this._Hosts.Values;
            }
        }

        /// <summary>
        /// 获取主机的数目。
        /// </summary>
        public int Count
        {
            get
            {
                return this._Hosts.Count;
            }
        }

        /// <summary>
        /// 创建并添加一个主机配置。
        /// </summary>
        /// <param name="hostName">主机的名称。</param>
        /// <param name="port">主机的端口。</param>
        /// <returns>返回创建成功的主机配置。</returns>
        public HostSetting AddHost(string hostName, int port)
        {
            return this.AddHost(hostName, port, this.ReturnsError);
        }

        /// <summary>
        /// 创建并添加一个主机配置。
        /// </summary>
        /// <param name="hostName">主机的名称。</param>
        /// <param name="port">主机的端口。</param>
        /// <param name="returnsError">指示在远程发生错误时是否返回异常的信息。</param>
        /// <returns>返回创建成功的主机配置。</returns>
        public HostSetting AddHost(string hostName, int port, bool returnsError)
        {
            RemotingApplication.ThorwEceptionWithIsOpen();

            if(this._Hosts == null) this._Hosts = new Dictionary<string, HostSetting>(StringComparer.OrdinalIgnoreCase);

            if(string.IsNullOrEmpty(hostName)) throw new ArgumentException("添加的主机名称不能为空！");
            if(this._Hosts.ContainsKey(hostName)) throw new ArgumentException("添加的主机名称“" + hostName + "”已存在。");

            HostSetting host = new HostSetting();
            host._Application = this;
            host.Name = hostName;
            host.Port = port;
            host.ReturnsError = returnsError;

            this._Hosts.Add(hostName, host);
            return host;
        }

        internal override void Initialization(XmlElement element)
        {
            base.Initialization(element);

            var hostElements = element.SelectNodes("Host");
            this._Hosts = new Dictionary<string, HostSetting>(hostElements.Count, StringComparer.OrdinalIgnoreCase);
            foreach(XmlElement hostElement in hostElements)
            {
                HostSetting host = new HostSetting();
                host._Application = this;
                host.Initialization(hostElement);
                this._Hosts.Add(host.Name, host);
            }
        }

        internal override SettingException CreateException(ServerErrorCode errorCode, string propertyName, string propertyValue)
        {
            return new SettingException(errorCode, propertyName, propertyValue)
            {
                _Application = this
            };
        }

        #region IEnumerable<HostSetting> 成员

        IEnumerator<HostSetting> IEnumerable<HostSetting>.GetEnumerator()
        {
            return this._Hosts.Values.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this._Hosts.Values.GetEnumerator();
        }

        #endregion

    }
}
